/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Sdrv_I2c_drv.h"
#include "Sdrv_I2c.h"
#include "I2c_Irq.h"
#include "I2c.h"
#include "Mcal_MemLibc.h"
#if (I2C_DEV_ERROR_DETECT == STD_ON)
#include "Det.h"
#endif /* (I2C_DEV_ERROR_DETECT == STD_ON) */

#define I2C_START_SEC_CODE_FAST
#include "I2c_MemMap.h"

/**
 * @brief Writes data to an I2C bus.
 *
 * This function writes a specified amount of data to an I2C bus.
 *
 * @param adap A pointer to an I2c_adap_dev_t structure.
 * @param buf A pointer to the buffer containing the data to be written.
 * @param wlen The length of the data to be written.
 * @param cur_len A pointer to the current length of data written.
 *
 * @return 0 on success, -1 on failure.
 */
static int sdrv_I2c_Write(I2c_adap_dev_t *adap, uint8 *buf,
                          uint16 wlen, uint16 *cur_len)
{
    uint16 flen, len;
    int ret = 0;

    if ((NULL_PTR == adap) || (NULL_PTR == buf) || (wlen < 1U))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_WRITE_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        ret = -1;
    }
    else
    {
        uint8 *tbuf = buf + *cur_len;

        flen = (uint16)sdrv_i2c_lld_get_wspace(adap->base);
        len = min(flen, wlen - *cur_len);
        *cur_len += len;

        while (len-- > 0U)
        {
            sdrv_i2c_lld_send_data(adap->base, *tbuf++);
        }

    }

    return ret;
}

/**
 * @brief Reads data from an I2C bus.
 *
 * This function reads a specified amount of data from an I2C bus.
 *
 * @param adap A pointer to an I2c_adap_dev_t structure.
 * @param buf A pointer to the buffer containing the data to be read.
 * @param rlen The length of the data to be read.
 * @param cur_len A pointer to the current length of data read.
 *
 * @return 0 on success, -1 on failure.
 */
static int sdrv_I2c_Read(I2c_adap_dev_t *adap, uint8 *buf,
                         uint16 rlen, uint16 *cur_len)
{
    uint16 flen, len;
    int ret = 0;

    if ((NULL_PTR == adap) || (NULL_PTR == buf) || (rlen < 1U))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_READ_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        ret = -1;
    }
    else
    {
        uint8 *rbuf = buf + *cur_len;

        flen = (uint16)sdrv_i2c_lld_get_rspace(adap->base);
        len = min(flen, rlen - *cur_len);
        *cur_len += len;

        while (len-- > 0U)
        {
            *rbuf++ = sdrv_i2c_lld_recv_data(adap->base);
        }
    }

    return ret;
}

/**
 * @brief Writes data to an I2C bus.
 *
 * This function writes a specified amount of data to an I2C bus.
 *
 * @param adap A pointer to an I2c_adap_dev_t structure.
 * @param buf A pointer to the buffer containing the data to be written.
 * @param wlen The length of the data to be written.
 *
 * @return 0 on success, -1 on failure due to invalid parameters, -2 on failure due to I2C timeout, -3 on failure due to I2C stuck.
 */
static int sdrv_I2c_pwrite(I2c_adap_dev_t *adap,  uint8 *buf, uint16 wlen)
{
    int ret = 0;
    uint16 len, flen;
    uint32 timeout;
    sdrv_I2c_dev_t *dev;
    uint32 int_st;

    // Get the device structure from the adapter's private data
    dev = (sdrv_I2c_dev_t *)adap->priv;

    // Initialize the timeout value from the device's configuration
    timeout = dev->mdev.timeout;

    // Loop until all data is written
    while (wlen > 0U)
    {
        int_st = sdrv_i2c_lld_get_int0_stat(adap->base);

        if (int_st & (uint32)SDRV_I2C_INT0_SDASTUCKLOW)
        {
            ret = -3; // SDA stuck low error
            break;
        }
        else if (int_st & SDRV_I2C_INT0_ERR_STAT)
        {
            if (I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
            {
                ret =  -4; // NACK error
                break;
            }
            else
            {
                ret =  -5; // Other error
                break;
            }
        }

        // Get the available write space
        flen = (uint16)sdrv_i2c_lld_get_wspace(adap->base);

        // If no space is available, wait for 1 microsecond and retry until timeout
        if (flen == 0U)
        {
            (void)Mcal_udelay(1U);

            if (timeout-- > 0U)
            {
                continue;
            }
            else
            {
                ret =  -1; // Timeout error
                break;
            }
        }

        // Reset the timeout and calculate the actual length to write
        timeout = dev->mdev.timeout;
        len = min(flen, wlen);
        wlen -= len;

        // Write the data byte by byte
        while (len-- > 0U)
        {
            sdrv_i2c_lld_send_data(adap->base, *buf++);
        }
    }

    if(ret == 0)
    {
        // Wait for the completion of the I2C command or an error
        timeout = dev->mdev.timeout;

        do
        {
            int_st = sdrv_i2c_lld_get_int0_stat(adap->base);

            // Check if the command is done
            if ((int_st & (uint32)SDRV_I2C_INT0_APBCMDDONE) > 0U)
            {
                break;
                // Check for a bus error or SDA stuck low error
            }
            else if (int_st & (uint32)SDRV_I2C_INT0_SDASTUCKLOW)
            {
                ret =  -3; // SDA stuck low error
                break;
            }
            else if ((int_st & (uint32)SDRV_I2C_INT0_ERR_STAT) > 0U)
            {
                if (I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
                {
                    ret =  -4; // NACK error
                    break;
                }
                else
                {
                    ret =  -5; // Other error
                    break;
                }
            }

            // Wait for 10 microseconds before checking again
            (void)Mcal_udelay(10U);
            timeout--;
        }
        while (timeout > 0U);

        // Return an error if timeout reached
        if (timeout <= 0U)
        {
            ret =  -2; // Timeout error
        }
    }

    return ret;
}
/**
 * Reads data from an I2C bus.
 *
 * @param adap A pointer to an I2c_adap_dev_t structure.
 * @param buf A pointer to the buffer to store the read data.
 * @param rlen The length of the data to be read.
 *
 * @return 0 on success, -1 on failure due to invalid parameters, -2 on failure due to I2C timeout, -3 on failure due to I2C stuck.
 */
static int sdrv_I2c_pread(I2c_adap_dev_t *adap, uint8 *buf, uint16 rlen)
{
    int ret = 0;
    uint16 len, flen;
    uint32 timeout;
    sdrv_I2c_dev_t *dev;
    uint32 int_st;

    // Get the device structure from the adapter's private data
    dev = (sdrv_I2c_dev_t *)adap->priv;

    // Initialize the timeout value from the device's configuration
    timeout = dev->mdev.timeout;

    // Loop until all requested data is read
    while (rlen > 0U)
    {
        int_st = sdrv_i2c_lld_get_int0_stat(adap->base);

        if (int_st & (uint32)SDRV_I2C_INT0_SDASTUCKLOW)
        {
            ret = -3; // SDA stuck low error
            break;
        }
        else if (int_st & SDRV_I2C_INT0_APBCMDABORT)
        {
            if (I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
            {
                ret = -4; // NACK error
                break;
            }
            else
            {
                ret = -5; // Other error
                break;
            }
        }

        // Get the available read space
        flen = (uint16)sdrv_i2c_lld_get_rspace(adap->base);

        // If no space is available, wait for 1 microsecond and retry until timeout
        if (flen == 0U)
        {
            (void)Mcal_udelay(1U);

            if (timeout-- > 0U)
            {
                continue;
            }
            else
            {
                ret = -1; // Timeout error
                break;
            }
        }

        // Reset the timeout and calculate the actual length to read
        timeout = dev->mdev.timeout;
        len = min(flen, rlen);
        rlen -= len;

        // Read the data byte by byte
        while (len-- > 0U)
        {
            *buf++ = sdrv_i2c_lld_recv_data(adap->base);
        }
    }

    if(ret == 0)
    {
        // Wait for the completion of the I2C command or an error
        timeout = dev->mdev.timeout;

        do
        {
            int_st = sdrv_i2c_lld_get_int0_stat(adap->base);

            // Check if the command is done
            if ((int_st & (uint32)SDRV_I2C_INT0_APBCMDDONE) > 0U)
            {
                break;
                // Check for a bus error or SDA stuck low error
            }
            else if (int_st & (uint32)SDRV_I2C_INT0_SDASTUCKLOW)
            {
                ret = -3; // SDA stuck low error
                break;
            }
            else if ((int_st & SDRV_I2C_INT0_ERR_STAT) > 0U)
            {
                if (I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
                {
                    ret = -4; // NACK error
                    break;
                }
                else
                {
                    ret = -5; // Other error
                    break;
                }
            }

            // Wait for 10 microseconds before checking again
            (void)Mcal_udelay(10U);
            timeout--;
        }
        while (timeout > 0U);

        // Return an error if timeout reached
        if (timeout <= 0U)
        {
            ret = -2; // Timeout error
        }
    }

    return ret;
}

/**
 * Disables all interrupts for the given I2C adapter device.
 *
 * @param adap pointer to the I2C adapter device
 *
 * @return void
 */
static void sdrv_I2c_disable_int_all(I2c_adap_dev_t *adap)
{
    sdrv_i2c_lld_unmask_int0(adap->base, 0x0U);
    sdrv_i2c_lld_unmask_int1(adap->base, 0x0U);
    sdrv_i2c_lld_unmask_int2(adap->base, 0x0U);
    sdrv_i2c_lld_unmask_int3(adap->base, 0x0U);
}

/**
 * Performs an I2C transfer operation using the given I2C adapter device.
 *
 * This function takes a pointer to an I2C adapter device, a pointer to an array of I2C messages,
 * and the number of messages in the array as parameters. It returns an integer indicating the
 * status of the transfer operation. A return value of 0 indicates a successful transfer, while
 * a negative return value indicates an error.
 *
 * @param adap A pointer to the I2C adapter device.
 * @param msgs A pointer to an array of I2C messages.
 * @param num The number of messages in the array.
 *
 * @return An integer indicating the status of the transfer operation.
 */
Std_ReturnType sdrv_I2c_xfer(I2c_adap_dev_t *adap, I2c_msg_t *msgs, uint8 num)
{
    Std_ReturnType errorId = E_OK;
    int ret = 0;
    // Retrieve private device structure from adapter
    sdrv_I2c_dev_t *dev = (sdrv_I2c_dev_t *)adap->priv;
    sdrv_I2c_mdev_t *mdev = &dev->mdev;

    // Copy message details from input to the mdev structure
    for (uint8 msgid = 0; msgid < num; msgid++)
    {
        mdev->msgs[msgid].addr = msgs[msgid].addr;
        mdev->msgs[msgid].buf = msgs[msgid].buf;
        mdev->msgs[msgid].len = msgs[msgid].len;
        mdev->msgs[msgid].rw_flag = msgs[msgid].rw_flag;
    }

    // Initialize the mdev structure with default values
    mdev->num = num;
    mdev->status = 0;
    mdev->cur_msg_idx = 0U;
    mdev->cur_msg_len = 0;
    mdev->cur_cmd_done = 0;
    mdev->cur_msg_stat = SDRV_I2C_MSG_IDLE;

    // Disable all I2C interrupts
    sdrv_I2c_disable_int_all(adap);

    // Clear I2C FIFO buffer
    if (sdrv_i2c_lld_clear_fifo(adap->base) < 0)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        // Report FIFO clear error if enabled
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSFER_ID,
                              (uint8)I2C_E_CLEAR_FIFO_FAILURE);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_CLEAR_FIFO_FAILURE;
    }
    else
    {
        // If polling mode is selected
        if (mdev->msgs[0].polling == (uint8)I2C_POLLING_MOD)
        {
            for (uint8 trans = 0U; trans < mdev->num; trans++)
            {
                // Clear interrupt status before each transaction
                sdrv_i2c_lld_clear_int_all(adap->base);
                mdev->cur_msg = &mdev->msgs[trans];

                /* set SlaveAddr, 7/10bit, read/write flag, data length */
                /*PRQA S 2985 5*/
                sdrv_i2c_lld_set_cmdcsr2(adap->base,
                                        (((uint32)(mdev->cur_msg->addr) & I2C_CMDCSR2_TAR_MASK) << I2C_CMDCSR2_TAR_BIT) |
                                        (((uint32)(mdev->cur_msg->addr_flag) & I2C_CMDCSR2_TARTYP_MASK) << I2C_CMDCSR2_TARTYP_BIT) |
                                        (((uint32)(mdev->cur_msg->rw_flag) & I2C_CMDCSR2_RWB_MASK) << I2C_CMDCSR2_RWB_BIT) |
                                        (((uint32)(mdev->cur_msg->len) & I2C_CMDCSR2_DATBYTENUM_MASK) << I2C_CMDCSR2_DATBYTENUM_BIT));

                /* Set automatic stop position, if current message is last */
                uint32 autostop = (trans == (mdev->num - 1U)) ? 0x1UL : 0x0UL;
                sdrv_i2c_lld_set_cmdcsr0(adap->base,
                                        ((I2C_MASTER_DOORBELL & I2C_CMDCSR0_DOORBELL_MASK) << I2C_CMDCSR0_DOORBELL_BIT) |
                                        ((autostop & I2C_CMDCSR0_AUTOSTOP_MASK) << I2C_CMDCSR0_AUTOSTOP_BIT)
                );

                // Perform read or write based on the rw_flag
                if (mdev->cur_msg->rw_flag == I2C_M_R)
                {
                    ret = sdrv_I2c_pread(adap, mdev->cur_msg->buf, mdev->cur_msg->len);
                }
                else
                {
                    ret = sdrv_I2c_pwrite(adap, mdev->cur_msg->buf, mdev->cur_msg->len);
                }

                // Handle transmission errors
                if (ret < 0)
                {
                    if (ret == -3)
                    {
                        adap->trans_state = I2C_STUCK_STATE;
                    }
                    else if(ret == -4)
                    {
                        adap->trans_state = I2C_NACK_STATE;
                    }
                    else
                    {
                        adap->trans_state = I2C_FAIL_STATE;
                    }

#if (I2C_DEV_ERROR_DETECT == STD_ON)
                    // Report transmission error if enabled
                    (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSFER_ID,
                                        (uint8)I2C_E_TRANSMIT_EXCEPTION);
#endif /* I2C_DEV_ERROR_DETECT */
                    errorId = I2C_E_TRANSMIT_EXCEPTION;
                    break;
                }
            }
        }
        // If main function mode is selected
        else if (mdev->msgs[0].polling == (uint8)I2C_MAINFUN_MOD)
        {
            adap->trans_state = I2C_BUSY_STATE;
        }
        // If interrupt mode is selected
        else if (mdev->msgs[0].polling == (uint8)I2C_INTR_MOD)
        {
            adap->trans_state = I2C_BUSY_STATE;
            sdrv_i2c_lld_unmask_int0(adap->base, SDRV_I2C_INT0_DEFAULT_MASK);
        }
        // Unknown polling mode, return error
        else
        {
            errorId = I2C_E_PARAM_INVALID;
        }
    }

    return errorId;
}
#define I2C_STOP_SEC_CODE_FAST
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"
static uint32 sdrv_I2c_Log2Uint(uint32 val)
{
    uint32 ret = 0U;
    uint32 valTemp = val;

    while (valTemp > 1U)
    {
        valTemp >>= 1U;
        ret++;
    }

    return ret;
}

/**
 * @brief Calculates the I2C timing configuration based on the given speed and clock.
 *
 * @param speed The I2C speed to calculate the timing configuration for.
 * @param clk The I2C clock frequency.
 * @param timing A pointer to store the calculated timing configuration.
 *
 * @return 0 on success, non-zero on failure.
 */
static int sdrv_I2c_get_timing_cfg(enum I2c_speed speed, uint32 clk, I2c_timeCfg_t timCfg,
                                   sdrv_I2c_timing_t *timing)
{
    // Initialize timing configuration structure and convert clock to kHz
    sdrv_I2c_timing_cfg_t cfg;
    Mcal_MemClr(&cfg, sizeof(cfg));
    uint32 clk_khz = clk / 1000U;
    timing->divs = clk_khz / 108000U;
    int ret = 0;

    // Calculate clock divider
    if (timing->divs > 0U)
    {
        clk_khz /= (timing->divs + 1U);
    }

    // Configure timing based on I2C speed mode
    if (speed == I2C_SSPEED)   // Standard Speed
    {
        cfg.timscll = CAL_SCLL(5000U, clk_khz);
        cfg.timtasclh = CAL_TA(timCfg.timSclh, clk_khz);
        cfg.timtascll = CAL_TA(150U, clk_khz);
        cfg.timtasdal = CAL_TA(150U, clk_khz);
        cfg.timdvdat = CAL_DVDAT(3400U, clk_khz);
        cfg.timunit = CAL_UNIT(6U);
        cfg.timmext = CAL_MEXT(0U, clk_khz);
        cfg.timsext = CAL_SEXT(0U, clk_khz);
        cfg.timstuck = CAL_STUCK(timCfg.timStuck, clk_khz);
        cfg.timsdarxhld = CAL_SDARXHLD(300U, clk_khz);
        cfg.timdatspl = CAL_DATSPL(2U);
        cfg.timbuf = CAL_BUF(5000U, clk_khz);
        cfg.timidle = CAL_IDLE(0U, clk_khz);
    }
    else if (speed == I2C_FSPEED)     // Fast Speed
    {
        cfg.timscll = CAL_SCLL(1300U, clk_khz);
        cfg.timtasclh = CAL_TA(timCfg.timSclh, clk_khz);
        cfg.timtascll = CAL_TA(150U, clk_khz);
        cfg.timtasdal = CAL_TA(150U, clk_khz);
        cfg.timdvdat = CAL_DVDAT(900U, clk_khz);
        cfg.timunit = CAL_UNIT(6U);
        cfg.timmext = CAL_MEXT(0U, clk_khz);
        cfg.timsext = CAL_SEXT(0U, clk_khz);
        cfg.timstuck = CAL_STUCK(timCfg.timStuck, clk_khz);
        cfg.timsdarxhld = CAL_SDARXHLD(300U, clk_khz);
        cfg.timdatspl = CAL_DATSPL(2U);
        cfg.timbuf = CAL_BUF(5000U, clk_khz);
        cfg.timidle = CAL_IDLE(0U, clk_khz);
    }
    else if (speed == I2C_PSPEED)     // Plus Speed
    {
        cfg.timscll = CAL_SCLL(500U, clk_khz);
        cfg.timtasclh = CAL_TA(60U, clk_khz);
        cfg.timtascll = CAL_TA(60U, clk_khz);
        cfg.timtasdal = CAL_TA(60U, clk_khz);
        cfg.timdvdat = CAL_DVDAT(450U, clk_khz);
        cfg.timunit = CAL_UNIT(6U);
        cfg.timmext = CAL_MEXT(0U, clk_khz);
        cfg.timsext = CAL_SEXT(0U, clk_khz);
        cfg.timstuck = CAL_STUCK(timCfg.timStuck, clk_khz);
        cfg.timsdarxhld = CAL_SDARXHLD(120U, clk_khz);
        cfg.timdatspl = CAL_DATSPL(2U);
        cfg.timbuf = CAL_BUF(5000U, clk_khz);
        cfg.timidle = CAL_IDLE(0U, clk_khz);
    }
    else if (speed == I2C_HSPEED)     // High Speed
    {
        cfg.timscll = CAL_SCLL(1300U, clk_khz);
        cfg.timtasclh = CAL_TA(timCfg.timSclh, clk_khz);
        cfg.timtascll = CAL_TA(150U, clk_khz);
        cfg.timtasdal = CAL_TA(150U, clk_khz);
        cfg.timdvdat = CAL_DVDAT(900U, clk_khz);
        cfg.timscll_h = CAL_SCLL(160U, clk_khz);
        cfg.timtasclh_h = CAL_TA(timCfg.timSclh_hs, clk_khz);
        cfg.timtascll_h = CAL_TA(30U, clk_khz);
        cfg.timtasdal_h = CAL_TA(30U, clk_khz);
        cfg.timdvdat_h = CAL_DVDAT(40U, clk_khz);
        cfg.timunit = CAL_UNIT(6U);
        cfg.timmext = CAL_MEXT(0U, clk_khz);
        cfg.timsext = CAL_SEXT(0U, clk_khz);
        cfg.timstuck = CAL_STUCK(timCfg.timStuck, clk_khz);
        cfg.timsdarxhld = CAL_SDARXHLD(60U, clk_khz);
        cfg.timdatspl = CAL_DATSPL(2U);
        cfg.timbuf = CAL_BUF(5000U, clk_khz);
        cfg.timidle = CAL_IDLE(0U, clk_khz);
    }
    else    /* (speed == I2C_USPEED)  Ultra Speed*/
    {
        cfg.timscll = CAL_SCLL(125U, clk_khz);
        cfg.timtasclh = CAL_TA(25U, clk_khz);
        cfg.timtascll = CAL_TA(25U, clk_khz);
        cfg.timtasdal = CAL_TA(25U, clk_khz);
        cfg.timdvdat = CAL_DVDAT(20U, clk_khz);
        cfg.timunit = CAL_UNIT(6U);
        cfg.timmext = CAL_MEXT(0U, clk_khz);
        cfg.timsext = CAL_SEXT(0U, clk_khz);
        cfg.timstuck = CAL_STUCK(timCfg.timStuck, clk_khz);
        cfg.timsdarxhld = CAL_SDARXHLD(20U, clk_khz);
        cfg.timdatspl = CAL_DATSPL(0U);
        cfg.timbuf = CAL_BUF(5000U, clk_khz);
        cfg.timidle = CAL_IDLE(0U, clk_khz);
    }

    if (cfg.timtasclh > I2C_PCR2_3_TIMTASCLH_MASK || cfg.timstuck > I2C_PCR4_TIMSTUCK_MASK)
    {
        ret = -1;
    }
    else
    {
        /*PRQA S 2985 5*/
        timing->pcr2 =  ((cfg.timscll & I2C_PCR2_3_TIMSCLL_MASK) << I2C_PCR2_3_TIMSCLL_BIT) |
                        ((cfg.timtasclh & I2C_PCR2_3_TIMTASCLH_MASK) << I2C_PCR2_3_TIMTASCLH_BIT) |
                        ((cfg.timtascll & I2C_PCR2_3_TIMTASCLL_MASK) << I2C_PCR2_3_TIMTASCLL_BIT) |
                        ((cfg.timtasdal & I2C_PCR2_3_TIMTASDAL_MASK) << I2C_PCR2_3_TIMTASDAL_BIT) |
                        ((cfg.timdvdat & I2C_PCR2_3_TIMDVDAT_MASK) << I2C_PCR2_3_TIMDVDAT_BIT);
        /*PRQA S 2985 5*/
        timing->pcr3 =  ((cfg.timscll_h & I2C_PCR2_3_TIMSCLL_MASK) << I2C_PCR2_3_TIMSCLL_BIT) |
                        ((cfg.timtasclh_h & I2C_PCR2_3_TIMTASCLH_MASK) << I2C_PCR2_3_TIMTASCLH_BIT) |
                        ((cfg.timtascll_h & I2C_PCR2_3_TIMTASCLL_MASK) << I2C_PCR2_3_TIMTASCLL_BIT) |
                        ((cfg.timtasdal_h & I2C_PCR2_3_TIMTASDAL_MASK) << I2C_PCR2_3_TIMTASDAL_BIT) |
                        ((cfg.timdvdat_h & I2C_PCR2_3_TIMDVDAT_MASK) << I2C_PCR2_3_TIMDVDAT_BIT);
        /*PRQA S 2985 4*/
        timing->pcr4 =  ((cfg.timunit & I2C_PCR4_TIMUNIT_MASK) << I2C_PCR4_TIMUNIT_BIT) |
                        ((cfg.timmext & I2C_PCR4_TIMMEXT_MASK) << I2C_PCR4_TIMMEXT_BIT) |
                        ((cfg.timsext & I2C_PCR4_TIMSEXT_MASK) << I2C_PCR4_TIMSEXT_BIT) |
                        ((cfg.timstuck & I2C_PCR4_TIMSTUCK_MASK) << I2C_PCR4_TIMSTUCK_BIT);
        /*PRQA S 2985 4*/
        timing->pcr5 =  ((cfg.timsdarxhld & I2C_PCR5_TIMSDARXHLD_MASK) << I2C_PCR5_TIMSDARXHLD_BIT) |
                        ((cfg.timdatspl & I2C_PCR5_TIMDATSMPL_MASK) << I2C_PCR5_TIMDATSMPL_BIT) |
                        ((cfg.timbuf & I2C_PCR5_TIMBUF_MASK) << I2C_PCR5_TIMBUF_BIT) |
                        ((cfg.timidle & I2C_PCR5_TIMIDLE_MASK) << I2C_PCR5_TIMIDLE_BIT);
    }

    return ret;
}
#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE_FAST
#include "I2c_MemMap.h"
/**
 * @brief This function handles the I2C master interrupt.
 *
 * It checks the interrupt status, handles errors, and performs read/write operations.
 *
 * @param irq The interrupt number.
 * @param arg A pointer to the I2c_adap_dev_t structure.
 *
 * @return An integer indicating the status of the interrupt handling.
 */
int sdrv_I2c_master_irq_handler(uint32 irq, I2c_adap_dev_t *arg)
{
    I2c_adap_dev_t *adap = arg;
    sdrv_I2c_dev_t *dev = adap->priv;
    sdrv_I2c_mdev_t *mdev = &dev->mdev;
    uint32 int_stat = sdrv_i2c_lld_get_int0_stat(adap->base);
    sdrv_i2c_lld_clear_intr0(adap->base, int_stat);

    boolean trigger_cleanup = FALSE;
    /*---------------------------------- Error Processing ----------------------------------*/
    if ((int_stat & SDRV_I2C_INT0_ERR_STAT) > 0U)
    {
        if (int_stat & SDRV_I2C_INT0_SDASTUCKLOW)
        {
            mdev->status = -1;
            adap->trans_state = I2C_STUCK_STATE;
        }
        else if ((int_stat & SDRV_I2C_INT0_APBCMDABORT) && I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
        {
            mdev->status = -1;
            adap->trans_state = I2C_NACK_STATE;
        }
        else
        {
            mdev->status = -1;
            adap->trans_state = I2C_FAIL_STATE;
        }

#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID,
                              (uint8)I2C_MASTER_IRQ_HANDLER_ID, (uint8)I2C_E_TRANSMIT_EXCEPTION);
#endif /* I2C_DEV_ERROR_DETECT */

        trigger_cleanup = TRUE;
    }

    /*---------------------------------- Normal Processing ----------------------------------*/
    if (!trigger_cleanup)
    {
        /* APB command done processing. */
        mdev->cur_cmd_done = ((int_stat & SDRV_I2C_INT0_APBCMDDONE) > 0U) ? 1 : 0;

        /* Check if the current message is idle and there are more messages to process */
        if ((mdev->cur_msg_stat == SDRV_I2C_MSG_IDLE) && (mdev->cur_msg_idx < mdev->num))
        {
            mdev->cur_msg = &mdev->msgs[mdev->cur_msg_idx];

            /* set SlaveAddr, 7/10bit, read/write flag, data length */
            /*PRQA S 2985 5*/
            sdrv_i2c_lld_set_cmdcsr2(adap->base,
                                    (((uint32)(mdev->cur_msg->addr) & I2C_CMDCSR2_TAR_MASK) << I2C_CMDCSR2_TAR_BIT) |
                                    (((uint32)(mdev->cur_msg->addr_flag) & I2C_CMDCSR2_TARTYP_MASK) << I2C_CMDCSR2_TARTYP_BIT) |
                                    (((uint32)(mdev->cur_msg->rw_flag) & I2C_CMDCSR2_RWB_MASK) << I2C_CMDCSR2_RWB_BIT) |
                                    (((uint32)(mdev->cur_msg->len) & I2C_CMDCSR2_DATBYTENUM_MASK) << I2C_CMDCSR2_DATBYTENUM_BIT));

            /* Set automatic stop position, if current message is last */
            uint32 autostop = (mdev->cur_msg_idx == mdev->num - 1U) ? 0x1UL : 0x0UL;
            sdrv_i2c_lld_set_cmdcsr0(
                adap->base,
                ((I2C_MASTER_DOORBELL & I2C_CMDCSR0_DOORBELL_MASK) << I2C_CMDCSR0_DOORBELL_BIT) |
                ((autostop & I2C_CMDCSR0_AUTOSTOP_MASK) << I2C_CMDCSR0_AUTOSTOP_BIT)
            );

            /* Unmask the corresponding read/write interrupt */
            if (mdev->cur_msg->rw_flag == I2C_M_R)  /* I2C_M_W / I2C_M_R */
            {
                sdrv_i2c_lld_unmask_int0(adap->base,
                                        SDRV_I2C_INT0_DEFAULT_MASK & ~SDRV_I2C_INT0_TXFWE);
            }
            else
            {
                sdrv_i2c_lld_unmask_int0(adap->base,
                                        SDRV_I2C_INT0_DEFAULT_MASK & ~SDRV_I2C_INT0_RXFWF);
            }
        }

        /* Execute read and write operations. */
        if (mdev->cur_msg_idx < mdev->num)
        {
            mdev->cur_msg_stat = SDRV_I2C_MSG_RW;
            if (mdev->cur_msg->rw_flag == I2C_M_R)
            {
                (void)sdrv_I2c_Read(adap, mdev->cur_msg->buf, mdev->cur_msg->len, &mdev->cur_msg_len);
            }
            else
            {
                (void)sdrv_I2c_Write(adap, mdev->cur_msg->buf, mdev->cur_msg->len, &mdev->cur_msg_len);
            }
        }

        /* Current message processing completed. */
        if (mdev->cur_msg_len >= mdev->cur_msg->len)
        {
            sdrv_i2c_lld_unmask_int0(adap->base,
                                     SDRV_I2C_INT0_DEFAULT_MASK & ~(SDRV_I2C_INT0_RXFWF | SDRV_I2C_INT0_TXFWE));
            mdev->cur_msg_stat = SDRV_I2C_MSG_IDLE;
            mdev->cur_msg_len = 0;
            mdev->cur_msg_idx++;
        }

        /* All messages have been processed. */
        if ((mdev->cur_msg_idx >= mdev->num) && (mdev->cur_cmd_done > 0))
        {
            adap->trans_state = I2C_IDLE_STATE;
            trigger_cleanup = TRUE;
        }
    }

    /*---------------------------------- Transfer complete Cleaning ----------------------------------*/
    if (trigger_cleanup)
    {
        sdrv_I2c_disable_int_all(adap);

        if (adap->I2cNotification != NULL_PTR)
        {
            adap->I2cNotification(adap->hwCh, adap->trans_state);
        }
    }

    return 0;
}

/**
 * @brief Handles the I2C job function.
 *
 * This function handles the I2C job function, including error handling,
 * command completion, and message processing. It takes a single parameter,
 * I2cId, which is the ID of the I2C device.
 *
 * @param channelId The ID of the I2C channelId.
 *
 * @return None
 */
static void I2c_JobHandleFuntion(uint8 channelId)
{
    uint32 coreId = I2c_GetCoreId();

    // Get the adapter device from the global I2C device array using the provided I2C ID
    I2c_adap_dev_t *adap = &I2c_Handler[coreId][channelId].adap;
    // Get the private device data associated with the adapter
    sdrv_I2c_dev_t *dev = adap->priv;
    // Get the master device structure from the private device data
    sdrv_I2c_mdev_t *mdev = &dev->mdev;
    // Get the current interrupt status
    uint32 int_stat = sdrv_i2c_lld_get_int0_stat(adap->base);
    // Clear the interrupt status
    sdrv_i2c_lld_clear_intr0(adap->base, int_stat);

    // Check if there is an error interrupt
    if ((int_stat & SDRV_I2C_INT0_ERR_STAT) > 0U)
    {
        // If SDA line is stuck low
        if (int_stat & SDRV_I2C_INT0_SDASTUCKLOW)
        {
            // Set device status to error and transition state to "stuck"
            mdev->status = -1;
            adap->trans_state = I2C_STUCK_STATE;
        }
        else if ((int_stat & SDRV_I2C_INT0_APBCMDABORT) && I2C_SLAVE_NACK == (sdrv_i2c_get_lld_psr0_stat(adap->base) & 0xff))
        {
            mdev->status = -1;
            adap->trans_state = I2C_NACK_STATE;
        }
        else
        {
            // Set device status to error and transition state to "failure"
            mdev->status = -1;
            adap->trans_state = I2C_FAIL_STATE;
        }

#if (I2C_DEV_ERROR_DETECT == STD_ON)
        // Report the error if error detection is enabled
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_JOBFUNCTION_ID,
                              (uint8)I2C_E_TRANSMIT_EXCEPTION);
#endif /* I2C_DEV_ERROR_DETECT */
    }
    else
    {
        // Check if APB command is done
        if ((int_stat & SDRV_I2C_INT0_APBCMDDONE) > 0U)
        {
            mdev->cur_cmd_done = 1;
        }
        else
        {
            mdev->cur_cmd_done = 0;
        }

        // Check if current message is idle and there are more messages to process
        if ((mdev->cur_msg_stat == SDRV_I2C_MSG_IDLE) && (mdev->cur_msg_idx < mdev->num))
        {
            mdev->cur_msg = &mdev->msgs[mdev->cur_msg_idx];

            /* set SlaveAddr, 7/10bit, read/write flag, data length */
            /*PRQA S 2985 5*/
            sdrv_i2c_lld_set_cmdcsr2(adap->base,
                                    (((uint32)(mdev->cur_msg->addr) & I2C_CMDCSR2_TAR_MASK) << I2C_CMDCSR2_TAR_BIT) |
                                    (((uint32)(mdev->cur_msg->addr_flag) & I2C_CMDCSR2_TARTYP_MASK) << I2C_CMDCSR2_TARTYP_BIT) |
                                    (((uint32)(mdev->cur_msg->rw_flag) & I2C_CMDCSR2_RWB_MASK) << I2C_CMDCSR2_RWB_BIT) |
                                    (((uint32)(mdev->cur_msg->len) & I2C_CMDCSR2_DATBYTENUM_MASK) << I2C_CMDCSR2_DATBYTENUM_BIT));

            /* auto strans stop bit, if current message is last */
            if (mdev->cur_msg_idx == mdev->num - 1U)
            {
                sdrv_i2c_lld_set_cmdcsr0(adap->base,
                                        ((I2C_MASTER_DOORBELL & I2C_CMDCSR0_DOORBELL_MASK) << I2C_CMDCSR0_DOORBELL_BIT) |
                                        ((0x1UL & I2C_CMDCSR0_AUTOSTOP_MASK) << I2C_CMDCSR0_AUTOSTOP_BIT));
            }
            else
            {
                sdrv_i2c_lld_set_cmdcsr0(adap->base,
                                        (((uint32)I2C_MASTER_DOORBELL & I2C_CMDCSR0_DOORBELL_MASK) << I2C_CMDCSR0_DOORBELL_BIT));
            }
        }

        // Check if there are more messages to process
        if (mdev->cur_msg_idx < mdev->num)
        {
            mdev->cur_msg_stat = SDRV_I2C_MSG_RW;

            // Perform read or write based on the message's read/write flag
            if (mdev->cur_msg->rw_flag > 0U)
            {
                (void)sdrv_I2c_Read(adap, mdev->cur_msg->buf, mdev->cur_msg->len, &mdev->cur_msg_len);
            }
            else
            {
                (void)sdrv_I2c_Write(adap, mdev->cur_msg->buf, mdev->cur_msg->len, &mdev->cur_msg_len);
            }
        }

        // Check if the current message is complete and the command is done
        if ((mdev->cur_msg_len >= mdev->cur_msg->len) && (mdev->cur_cmd_done > 0))
        {
            mdev->cur_cmd_done = 0;
            mdev->cur_msg_stat = SDRV_I2C_MSG_IDLE;
            mdev->cur_msg_len = 0;

            // If all messages are processed, set the adapter state to idle
            if (mdev->cur_msg_idx >= mdev->num - 1U)
            {
                adap->trans_state = I2C_IDLE_STATE;
            }

            mdev->cur_msg_idx++;
        }
    }

    return;
}
#define I2C_STOP_SEC_CODE_FAST
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"
/**
 * Performs the initialization of the I2C adapter device.
 *
 * This function takes a pointer to an I2c_adap_dev_t structure as a parameter.
 * It initializes the I2C adapter device according to the specified operation mode and speed.
 * The function returns the initialization state of the I2C adapter device.
 *
 * @param adap A pointer to the I2c_adap_dev_t structure.
 *
 * @return The initialization state of the I2C adapter device.
 */
I2c_init_state_t sdrv_I2c_init(I2c_adap_dev_t *adap)
{
    sdrv_I2c_timing_t timing; // Initialize timing structure
    Mcal_MemClr(&timing, sizeof(timing));
    sdrv_I2c_dev_t *dev = adap->priv; // Get private device data from adapter
    I2c_init_state_t initState;

    if (adap->opmode == I2C_MASTER)
    {
        dev->mdev.timeout = SDRV_I2C_TIMEOUT; // Set timeout for master device
        dev->mdev.event = NULL; // Initialize event to NULL
        dev->mdev.status = 0; // Initialize status to 0
    }

    /* disable controller */
    sdrv_i2c_lld_disable(adap->base); // Disable the I2C controller

    /* calculate controller internal timing */
    if (0 != sdrv_I2c_get_timing_cfg(adap->speed, adap->clk, adap->i2cTimeCfg,
                                     &timing)) // Get timing configuration based on speed and clock
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_INIT_ID,
                              (uint8)I2C_E_PARAM_INVALID); // Report error if reset fails
#endif /* I2C_DEV_ERROR_DETECT */
        initState = I2C_UNINIT_STATE;
    }
    else if (0 != sdrv_i2c_lld_reset(adap->base))   // Reset the I2C controller
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_INIT_ID,
                              (uint8)I2C_E_RESET_EXCEPTION); // Report error if reset fails
#endif /* I2C_DEV_ERROR_DETECT */
        initState = I2C_UNINIT_STATE;
    }
    else
    {
        /* set controller operation mode */
        if (adap->opmode == I2C_MASTER)
        {
            sdrv_i2c_lld_set_opmode(adap->base, SDRV_I2C_MASTER); // Set operation mode to master
        }

        /* set controller speed mode and prescale value */
        if (adap->speed == I2C_HSPEED)
        {
            sdrv_i2c_lld_set_speed(adap->base, ((SDRV_I2C_HSPEED & I2C_PCR0_SPEED_MASK) << I2C_PCR0_SPEED_BIT) |
                                   ((timing.divs & I2C_PCR0_PRESCALE_MASK) << I2C_PCR0_PRESCALE_BIT)); // Set high-speed mode
        }
        else if (adap->speed == I2C_USPEED)
        {
            sdrv_i2c_lld_set_speed(adap->base, ((SDRV_I2C_USPEED & I2C_PCR0_SPEED_MASK) << I2C_PCR0_SPEED_BIT) |
                                   ((timing.divs & I2C_PCR0_PRESCALE_MASK) << I2C_PCR0_PRESCALE_BIT)); // Set ultra-speed mode
        }
        else
        {
            /*PRQA S 2986 2*/
            sdrv_i2c_lld_set_speed(adap->base, ((SDRV_I2C_NSPEED & I2C_PCR0_SPEED_MASK) << I2C_PCR0_SPEED_BIT) |
                                   ((timing.divs & I2C_PCR0_PRESCALE_MASK) << I2C_PCR0_PRESCALE_BIT)); // Set normal-speed mode
        }

        /* set controller timing parameter */
        sdrv_i2c_lld_set_timing(adap->base,
                                timing.pcr2, timing.pcr3, timing.pcr4, timing.pcr5); // Set timing parameters for the controller
        /* set controller fifo watermark */
        sdrv_i2c_lld_set_watermark(adap->base, SDRV_I2C_TX_WML,
                                   SDRV_I2C_RX_WML); // Set FIFO watermark levels
        /* Mcal_PmuCounterInit(); (void)Mcal_udelay is needed for I2c driver, Mcal_PmuCounterInit in main.c*/
        /* recommended to enable the controller after initialization */
        sdrv_i2c_lld_enable(adap->base); // Enable the I2C controller after initialization
        adap->trans_state = I2C_IDLE_STATE; // Set transaction state to idle
        adap->adap_State = I2C_ADAP_IDLE; // Set adapter state to idle

        initState = I2C_INIT_STATE;// Return initialized state
    }

    return initState;
}

/**
 * Deinitialize the I2C driver.
 *
 * @param adap A pointer to the I2C adapter device structure.
 *
 * @return The Deinitialize state of the I2C driver.
 */
Std_ReturnType sdrv_I2c_deinit(I2c_adap_dev_t *adap)
{
    Std_ReturnType ret = E_OK;

    sdrv_I2c_disable_int_all(adap); // Disable I2C all interrupts
    sdrv_i2c_lld_clear_int_all(adap->base); // Clear any pending interrupts
    sdrv_i2c_lld_disable(adap->base); // Disable I2C low-level driver

    if (0 != sdrv_i2c_lld_reset(adap->base)) // Reset the I2C controller
    {
        ret = I2C_E_RESET_EXCEPTION;
    }

    return ret;
}

/**
 * Recovers the I2C adapter device from the bus stuck.
 *
 * @param adap A pointer to the I2C adapter device structure.
 *
 * @return Returns 0 if the recovery is successful, -1 if there is an error, and -2 if the recovery times out.
 */
int sdrv_I2c_recover(I2c_adap_dev_t *adap)
{
    int ret = -2;  /* Set to timeout status by default. */
    sdrv_I2c_dev_t *dev = adap->priv;
    uint32 timeout;
    uint32 int_stat;

    /* Hardware Initialization Process */
    sdrv_i2c_lld_disable(adap->base);
    sdrv_i2c_lld_clear_int_all(adap->base);
    sdrv_i2c_lld_reset(adap->base);
    sdrv_i2c_lld_set_busclr(adap->base);
    sdrv_i2c_lld_enable(adap->base);

    /* Phase 1: Wait for bus clear to complete */
    timeout = dev->mdev.timeout;
    do {
        if (sdrv_i2c_lld_get_busclr_stat(adap->base) == 0)
        {
            break;  /* Bus cleared. Jump out of loop. */
        }
        (void)Mcal_udelay(1U);
        timeout--;
    } while (timeout > 0U);

   /* Proceed to phase 2 only if phase 1 is successful */
    if (timeout > 0U)
    {
        /* Phase 2: Waiting for bus clear result */
        timeout = dev->mdev.timeout;
        do {
            int_stat = sdrv_i2c_lld_get_int0_stat(adap->base);
            (void)Mcal_udelay(1U);
            timeout--;
        } while (!(int_stat & (SDRV_I2C_INT0_BUSCLRPASS | SDRV_I2C_INT0_BUSCLRERR)) && (timeout > 0U));

        /* Judge the results of the second stage */
        if (timeout > 0U) {
            ret = (int_stat & SDRV_I2C_INT0_BUSCLRPASS) ? 0 : -1;  /* Return value based on the status setting. */
        }
        /* If the second phase times out, it will default to -2. */
    }
    /* If the first phase times out, it will default to -2. */

    sdrv_i2c_lld_clear_int_all(adap->base);
    return ret;
}

#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"

/**
 * Initializes the I2C adapter with the provided configuration.
 *
 * @param[in] adap  Pointer to the I2C adapter device structure.
 * @param[in] cfg   Pointer to the I2C adapter configuration structure.
 *
 * @retval  0  I2C adapter initialized successfully.
 * @retval -1  I2C adapter initialization failed.
 */
static int I2c_adap_earlyinit(I2c_adap_dev_t *adap, const I2c_adap_cfg_t *cfg)
{
    adap->base = cfg->base;
    adap->clk = cfg->clk;
    adap->enable = cfg->enable;
    adap->opmode = cfg->opmode;
    adap->speed = cfg->speed;
    adap->I2cNotification = cfg->I2cNotification;
    adap->i2cTimeCfg.timStuck = cfg->timStuck;
    adap->i2cTimeCfg.timSclh = cfg->timSclh;
    adap->i2cTimeCfg.timSclh_hs = cfg->timSclh_hs;

    return 0;
}

/**
 * Performs the initialization of the I2C adapter device.
 *
 * This function takes a pointer to an I2c_adap_dev_t structure, a pointer to an I2c_adap_cfg_t structure,
 * and the I2C adapter device ID as parameters. It returns a pointer to the I2c_adap_dev_t structure.
 *
 * @param dev A pointer to the I2c_adap_dev_t structure.
 * @param channelId The ID of the I2C channel to handle.
 * @param cfg A pointer to the I2c_adap_cfg_t structure.
 * @param hwChannel The I2C adapter device ID.
 *
 * @return A pointer to the I2c_adap_dev_t structure.
 */
I2c_adap_dev_t *sdrv_I2c_adap_probe(sdrv_I2c_dev_t *dev, uint8 ChannelId, const I2c_adap_cfg_t *cfg, I2c_chan_id hwChannel )
{
    I2c_adap_dev_t *adap = &dev[ChannelId].adap;

    adap->hwCh = hwChannel;
    /*PRQA S 0315 1*/
    adap->priv = &dev[ChannelId];

    (void)I2c_adap_earlyinit(adap, cfg);

    return adap;
}
#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE_FAST
#include "I2c_MemMap.h"
/**
 * @brief Handles the main I2C communication process for a given I2C channel.
 *
 * This function is responsible for managing the main communication process of an I2C
 * channel identified by `I2cId`. It first checks if the I2C channel is initialized
 * and currently in a busy state. If both conditions are met, it retrieves the
 * private device structure associated with the channel and determines the
 * transmission mode. If the transmission mode is set to I2C_MAINFUN_MOD,
 * the function proceeds to handle the I2C job.
 *
 * @param channelId The ID of the I2C channel to handle.
 */
void I2c_MainFunctionHandling(uint8 channelId)
{
    uint32 coreId = I2c_GetCoreId();

    /*PRQA S 3415 2*/
    if ((I2c_GetInitState(channelId) == I2C_INIT_STATE) &&
            (I2c_GetTranState(channelId) == I2C_BUSY_STATE))
    {

        sdrv_I2c_dev_t *dev = I2c_Handler[coreId][channelId].adap.priv;
        uint8 trans_mod = dev->mdev.msgs[0].polling;

        if (trans_mod == (uint8)I2C_MAINFUN_MOD)
        {
            I2c_JobHandleFuntion(channelId);
        }
    }
}

uint32 I2c_GetCoreId(void)
{
    return Mcal_GetCpuIndex();
}

#define I2C_STOP_SEC_CODE_FAST
#include "I2c_MemMap.h"
